Filtrovani kbmMemTable v druhem vlakne
Otázka od: Karel Pecinka
20. 10. 2004 19:10
Zdravim,
mam aplikaci, ve ktere uzivatel pise do Editu text a okamzite po napsani
se mu filtruje memory tabulka, ktera muze mit az 10.000 nebo vice radku.
U takoveho mnozstvi uz se stava, ze uzivatel napise rychle slovo a pak
musi cekat a vidi, jak se pomalu do editu pripisujou pismenka a zuzuje
se vyber. Je to sice pouzitelne, ale neni to prilis efektni.
Potreboval bych to vymyslet tak, aby uzivatel mohl nerusene psat a
filtrovani probihalo v jinem vlakne. Nebo napr. az kdyz pul sekundy
nepise. Zkousel jsem presouvat to filtrovani do druhyho vlakna, ale je
to problematicky, protoze to zase hlavni vlakno musi zobrazit a tak
dochazi ke konfliktum.
Poradite nekdo, jak se da vyresit tento problem?
Diky.
Karel
Odpovedá: Milan Tomes
20. 10. 2004 19:32
Ja bych to resil rozhodne pomoci prodlevy. Neni to celkem nic sloziteho -
mohu zaslat priklad pouziti...
S pozdravem
Milan Tomes
> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Karel Pecinka
> Sent: Wednesday, October 20, 2004 8:11 PM
>
> mam aplikaci, ve ktere uzivatel pise do Editu text a okamzite po napsani
> se mu filtruje memory tabulka, ktera muze mit az 10.000 nebo vice radku.
>
> filtrovani probihalo v jinem vlakne. Nebo napr. az kdyz pul sekundy
> nepise. Zkousel jsem presouvat to filtrovani do druhyho vlakna, ale je
Odpovedá: Ludek Finstrle
21. 10. 2004 9:01
> filtrovani probihalo v jinem vlakne. Nebo napr. az kdyz pul sekundy
> nepise.
Tady bych hodil timer do OnKeyDown ci Press nebo kam by se to nejvice
hodilo.
Luf
Odpovedá: Jan Novak
21. 10. 2004 21:10
> uzivatel pise do Editu text a okamzite po napsani
> se mu filtruje memory tabulka, ktera muze mit az 10.000
To je typicky priklad, kdy to vlakna jen zbytecne zakomplikuji.
Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
Staci 2 staticke boolean promenne Nacitam a NovyFiltr, ktere pri
startu programu nastavis na false a pak Edit1.OnChange vypada nejak
takhle:
begin
if Nacitam then // zabraneni rekurze
begin
NovyFiltr := true;
exit;
end;
Nacitam := true;
repeat
begin
Radky.Zrus;
Radky.Filtr := Edit1.Text; // aktualni filtr
NovyFiltr := false;
LastPM := Now;
while not Radky.Hotovo do
begin
if NovyFiltr then break; // prerus nacitani po zmene editu
Radky.NactiDalsi;
if (Now-LastPM) > (200*MS) then
begin // jednou za 200 ms
LastPM := Now;
Application.ProcessMessages;
end;
end;
end until NovyFiltr;
Nacitam := false;
end;
MS je konstanta pro trvani milisekundy MS=1./(24*60*60*1000)
Odpovedá: Milan Tomes
22. 10. 2004 5:16
Tak tohle povazuji take za dost hruzne reseni.
Tady je reseni *BEZ* pouziti ProcessMessages:
interface
type
TMyEdit = class (TEdit)
private
FOnLateChange: TNotifyEvent;
FInterval: cardinal;
FTimerHWND: HWND;
procedure FinalizeTimer;
protected
procedure DoLateChange;
procedure UpdateTimer;
procedure WndProc(var Message: TMessage); override;
procedure KeyPress(var Key: Char); override;
public
destructor Destroy; override;
published
property OnLateChange: TNotifyEvent read FOnLateChange write
FOnLateChange;
property Interval: cardinal read FInterval write FInterval;
end;
implementation
const
UpdateTimer_IDEvent = 1;
{ TMyEdit }
destructor TMyEdit.Destroy;
begin
FinalizeTimer;
inherited;
end;
procedure TMyEdit.DoLateChange;
begin
FinalizeTimer;
if Assigned(FOnLateChange) then
FOnLateChange(self);
end;
procedure TMyEdit.KeyPress(var Key: Char);
begin
inherited;
UpdateTimer;
end;
procedure TMyEdit.UpdateTimer;
begin
FinalizeTimer;
if Interval <> 0 then
if setTimer(self.Handle, UpdateTimer_IDEvent, Interval, nil) = 0 then
raise Exception.Create('Nelze vytvorit casovac !!!')
else
FTimerHWND := self.Handle;
end;
procedure TMyEdit.WndProc(var Message: TMessage);
begin
if (Message.Msg = WM_TIMER) and (Message.WParam = UpdateTimer_IDEvent)
then
DoLateChange
else
inherited;
end;
procedure TMyEdit.FinalizeTimer;
begin
if FTimerHWND <> 0 then
begin
killTimer(FTimerHWND, UpdateTimer_IDEvent);
FTimerHWND := 0;
end;
end;
Interval je hodnota v milisekundach (- podivej se na WinAPI funkci
setTimer). Pokud je od prvniho stisku klavesy po dobu intervalu stisknuta
klavesa je timer zrusen a vzapeti znovu vytvoren (kvuli novemu pocitani
intervalu). V pripade klidu je po uplynuti zadaneho intervalu odeslana
timerem zprava WM_TIMER do WndProc a ta vyvola event OnLateChange.
S pozdravem
Milan Tomes
P.S.: Psal jsem to jen v Outlooku, takze nezarucuji funkcnost
> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Jan Novak
> Sent: Thursday, October 21, 2004 10:11 PM
>
> > uzivatel pise do Editu text a okamzite po napsani
> > se mu filtruje memory tabulka, ktera muze mit az 10.000
>
> To je typicky priklad, kdy to vlakna jen zbytecne zakomplikuji.
> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
Odpovedá: Jan Novak
22. 10. 2004 6:44
>> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
> Tak tohle povazuji take za dost hruzne reseni.
Nezlob se na mne, ale to, cemu rikas 'reseni' ty, je jen nekolik
obrazovek sloziteho kodu, ktere nedelaji nic, nez ze po urcitem case
od zmeny Editu poslou zpravu hlavnimu threadu. Nemas tam vubec nic o
tom, jak se od ni v dalsim threadu nastartuje nacitani a jak se
pripadne prerusi predchozi nacitani, pokud bylo rozbehnuto. Neni tam
ani to, jak ten thread po nacteni jedne polozky zobrazi jeji obsah v
nejakem gridu, ktery je soucasti VCL a tedy se musi volat pres
Synchronize.
Zkus si to napsat cele a pak se vyslov, co je 'hruzne' a co je
prehledne a jasne reseni.
Odpovedá: Milan Tomes
22. 10. 2004 7:06
Cele reseni problemu je opravdu zalozeno na startovani timeru. Snazil jsem
se o reseni elementarniho problemu a sice toho aby se se zpozdenim vyvolala
udalost OnChange. Pokud se Ti toto nelibi, tak se prosim rychle uklidni a
prestan s takovymito vypady. Netvrdil jsem, ze je to reseni pomoci vlakna,
protoze se plne ztotoznuji, ze ve vlakne by - kdyz uz - melo probihat
vlastni cteni dat a ne zpracovani pauzy, ktera je uzce zavisla na VCL
komponente a tudiz veskere volani musi byt provadeno v kontextu hlavniho
threadu. Jestli je pro Tebe tento kod slozity je samozrejme otazka jina - ja
osobne vubec nechapu co je na tomto kodu sloziteho - jedna se o 6 metod
jejichz delka nepresahuje 6 jednoduchych radku kodu. BTW cely kod jsem psal
v Outlooku a jeho napsani netrvalo dele nez 5 minut
Cele reseni jsem napsal a neustale povazuji Tve reseni za hruzne.
Omlouvam se, ze jsem hluboce urazil Tve city tim, ze jsem vyslovil svuj
nazor na kvalitu Tveho reseni. Az budes neco potrebovat Ty, tak verim, ze se
vsichni strasne pretrhnout kdyz vidi Tvoji reakci. Ja osobne nepomohu uz jen
proto, ze se budu obavat abys me nahodou za univerzalnost a tim take moznou
vetsi narocnost na znalosti a slozitost nahodou znovu neserval
S pozdravem
Milan Tomes
P.S.: Tusim, ze tazatel to jiz vyresil prave vytvoreni one nove komponenty,
jejiz kod jsem posilal
P.P.S.: Podivej se na thread, kde se pouziti Application.ProcessMessages
velice kritizuje.
> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Jan Novak
> Sent: Friday, October 22, 2004 7:45 AM
>
> >> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
>
> > Tak tohle povazuji take za dost hruzne reseni.
>
> Nezlob se na mne, ale to, cemu rikas 'reseni' ty, je jen nekolik
> obrazovek sloziteho kodu, ktere nedelaji nic, nez ze po urcitem case
> od zmeny Editu poslou zpravu hlavnimu threadu. Nemas tam vubec nic o
> tom, jak se od ni v dalsim threadu nastartuje nacitani a jak se
> pripadne prerusi predchozi nacitani, pokud bylo rozbehnuto. Neni tam
> ani to, jak ten thread po nacteni jedne polozky zobrazi jeji obsah v
> nejakem gridu, ktery je soucasti VCL a tedy se musi volat pres
> Synchronize.
>
> Zkus si to napsat cele a pak se vyslov, co je 'hruzne' a co je
> prehledne a jasne reseni.
>
>
>
>
Odpovedá: Karel Kral
22. 10. 2004 8:19
Diky, pekne a elegantni, urcite se mi to bude hodit. Proc nepouzivas
TTimer z Delphi?
Milan Tomes napsal(a):
> Tak tohle povazuji take za dost hruzne reseni.
> Tady je reseni *BEZ* pouziti ProcessMessages:
>
> interface
>
> type
> TMyEdit = class (TEdit)
> private
> FOnLateChange: TNotifyEvent;
> FInterval: cardinal;
> FTimerHWND: HWND;
> procedure FinalizeTimer;
> protected
> procedure DoLateChange;
> procedure UpdateTimer;
> procedure WndProc(var Message: TMessage); override;
> procedure KeyPress(var Key: Char); override;
> public
> destructor Destroy; override;
> published
> property OnLateChange: TNotifyEvent read FOnLateChange write
> FOnLateChange;
> property Interval: cardinal read FInterval write FInterval;
--
______________________________________________________
Karel Kral, vedouci odd. IT / IT manager
Purus, s.r.o., Cezavy 627, 664 56 Blucina, CZ
Tel: 547 235 000, 602 552 432, Fax: 547 231 203
E-Mail: mailto:kral@purus.cz, WWW: http://www.purus.cz
______________________________________________________
Odpovedá: Milan Tomes
22. 10. 2004 8:25
Protoze se zbytecne alokuje dalsi handle pouze pro zachytavani zpravy
WM_TIMER (viz. Classes.AllocateHwnd). Prijde mi to uplne zbytecne
S pozdravem
Milan Tomes
P.S.: Nemuzu si odpustit rypnuti a podekovat za pochvalu )))))))))))
Admin - I'm so sorry
> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Karel Kral
> Sent: Friday, October 22, 2004 9:19 AM
>
> Diky, pekne a elegantni, urcite se mi to bude hodit. Proc nepouzivas
> TTimer z Delphi?
>
> Milan Tomes napsal(a):
> > Tak tohle povazuji take za dost hruzne reseni.
> > Tady je reseni *BEZ* pouziti ProcessMessages:
> >
> > interface
> >
> > type
> > TMyEdit = class (TEdit)
> > private
> > FOnLateChange: TNotifyEvent;
> > FInterval: cardinal;
> > FTimerHWND: HWND;
> > procedure FinalizeTimer;
> > protected
> > procedure DoLateChange;
> > procedure UpdateTimer;
> > procedure WndProc(var Message: TMessage); override;
> > procedure KeyPress(var Key: Char); override;
> > public
> > destructor Destroy; override;
> > published
> > property OnLateChange: TNotifyEvent read FOnLateChange write
> > FOnLateChange;
> > property Interval: cardinal read FInterval write FInterval;
Odpovedá: Karel Pecinka
22. 10. 2004 8:51
Pouzil jsem reseni Milana a je opravdu super, vrele doporucuji. Trochu
jsem si ho teda upravil, timer se nespousti v KeyPress ale v Change, coz
odchyti i napr. stisk Delete atd. Pridal jsem si, ze kdyz interval je 0
tak se udalost pusti az po Enteru. Do konfigurace jsem si hodil
nastaveni prodlevy, aby si uzivatel podle poctu polozek ceniku,
rychlosti pocitace a rychlosti jeho psani mohl nastavit prodlevu, ktera
mu umozni pracovat s programem co nejpohodlneji. Milanovi moc dekuju.
Co se tyce druheho reseni, je opravdu nic moc. Filtrovani totiz provadim
jednim prikazem a o zbytek se stara komponenta tabulky. Mohl bych se
nabourat do zdrojaku a nejak tam davat to processmessages ale reseni
Milana Tomese je naprosto jednoduche, nevyzaduje zadne upravy kodu a
uzivatel ziskava naproste pohodli pri praci.
Karel
> -----Original Message-----
> From: delphi-l-owner@clexpert.cz
> [mailto:delphi-l-owner@clexpert.cz] On Behalf Of Milan Tomes
> Sent: Friday, October 22, 2004 8:07 AM
> To: delphi-l@clexpert.cz
> Subject: Re: Filtrovani kbmMemTable v druhem vlakne
>
>
> Cele reseni problemu je opravdu zalozeno na startovani
> timeru. Snazil jsem se o reseni elementarniho problemu a sice
> toho aby se se zpozdenim vyvolala udalost OnChange. Pokud se
> Ti toto nelibi, tak se prosim rychle uklidni a prestan s
> takovymito vypady. Netvrdil jsem, ze je to reseni pomoci
> vlakna, protoze se plne ztotoznuji, ze ve vlakne by - kdyz uz
> - melo probihat vlastni cteni dat a ne zpracovani pauzy,
> ktera je uzce zavisla na VCL komponente a tudiz veskere
> volani musi byt provadeno v kontextu hlavniho threadu. Jestli
> je pro Tebe tento kod slozity je samozrejme otazka jina - ja
> osobne vubec nechapu co je na tomto kodu sloziteho - jedna se
> o 6 metod jejichz delka nepresahuje 6 jednoduchych radku
> kodu. BTW cely kod jsem psal v Outlooku a jeho napsani
> netrvalo dele nez 5 minut
>
> Cele reseni jsem napsal a neustale povazuji Tve reseni za hruzne.
>
> Omlouvam se, ze jsem hluboce urazil Tve city tim, ze jsem
> vyslovil svuj nazor na kvalitu Tveho reseni. Az budes neco
> potrebovat Ty, tak verim, ze se vsichni strasne pretrhnout
> kdyz vidi Tvoji reakci. Ja osobne nepomohu uz jen proto, ze
> se budu obavat abys me nahodou za univerzalnost a tim take
> moznou vetsi narocnost na znalosti a slozitost nahodou znovu
> neserval
>
> S pozdravem
>
> Milan Tomes
>
> P.S.: Tusim, ze tazatel to jiz vyresil prave vytvoreni one
> nove komponenty, jejiz kod jsem posilal
> P.P.S.: Podivej se na thread, kde se pouziti
> Application.ProcessMessages velice kritizuje.
>
> > [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Jan Novak
> > Sent: Friday, October 22, 2004 7:45 AM
> >
> > >> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
> >
> > > Tak tohle povazuji take za dost hruzne reseni.
> >
> > Nezlob se na mne, ale to, cemu rikas 'reseni' ty, je jen nekolik
> > obrazovek sloziteho kodu, ktere nedelaji nic, nez ze po
> urcitem case
> > od zmeny Editu poslou zpravu hlavnimu threadu. Nemas tam
> vubec nic o
> > tom, jak se od ni v dalsim threadu nastartuje nacitani a jak se
> > pripadne prerusi predchozi nacitani, pokud bylo rozbehnuto.
> Neni tam
> > ani to, jak ten thread po nacteni jedne polozky zobrazi
> jeji obsah v
> > nejakem gridu, ktery je soucasti VCL a tedy se musi volat pres
> > Synchronize.
> >
> > Zkus si to napsat cele a pak se vyslov, co je 'hruzne' a co je
> > prehledne a jasne reseni.
> >
> >
> >
> >
>
>
>